﻿using IdentityServer4.Models;
using IdentityServer4.Validation;
using System.Collections;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;

namespace Idp_Login._idp_config_
{
    //https://stackoverflow.com/questions/43894146/identityserver4-add-custom-default-claim-to-client-principal-for-client-credent
    /// <summary>
    /// 
    /// </summary>
    public class DefaultClientClaimsAdder : ICustomTokenRequestValidator
    {
        private class ObjectComparer : IComparer
        {
            int IComparer.Compare(object x, object y)
            {
                if (!object.Equals(x, y))
                {
                    return -1;
                }

                return 0;
            }
        }

        private static int GetIEnumerableCount(IEnumerable enumerable)
        {
            if (enumerable is ICollection collection) { return collection.Count; }
            if (enumerable is IList list) { return list.Count; }
            return -1;
        }


        private static (bool IsEuqal, string Reason) AreCollectionsEqual(IEnumerable expected, IEnumerable actual, IComparer comparer = null)
        {

            if (expected == actual)
            {
                return (true, "BothCollectionsSameReference");
            }

            if (expected == null)
            {
                return (false, "expected is null");
            }

            if (actual == null)
            {
                return (false, "actual is null");
            }

            //if (expected.Count != actual.Count)
            //{
            //    return (false, "NumberOfElementsDiff");
            //}
            int expectedCount = GetIEnumerableCount(expected);
            int actualCount = GetIEnumerableCount(actual);

            if (expectedCount != -1 && actualCount != -1)
            {
                if (expectedCount != actualCount)
                {
                    return (false, "NumberOfElementsDiff");
                }
            }

            IEnumerator enumerator = expected.GetEnumerator();
            IEnumerator enumerator2 = actual.GetEnumerator();

            if (comparer == null)
            {
                comparer = new ObjectComparer();
            }
            int num = 0;
            while (enumerator.MoveNext() && enumerator2.MoveNext())
            {
                if (comparer.Compare(enumerator.Current, enumerator2.Current) != 0)
                {
                    return (false, "ElementsAtIndexDontMatch:" + num);
                }

                num++;
            }
            return (true, "BothCollectionsSameReference");

        }

        public Task ValidateAsync(CustomTokenRequestValidationContext context)
        {
            var client = context.Result.ValidatedRequest.Client;
            if (client.ClientId == "consoleClient")
            {
                (bool IsEuqal, string _) = DefaultClientClaimsAdder.AreCollectionsEqual(client.AllowedGrantTypes.ToList(), GrantTypes.ClientCredentials);

                if (IsEuqal)
                {
                    context.Result.ValidatedRequest.Client.AlwaysSendClientClaims = true; //忽视客户端的值
                }
                var cliams = context.Result.ValidatedRequest.ClientClaims;
                cliams.Add(new Claim(IdentityModel.JwtClaimTypes.Role, "Admin"));
                cliams.Add(new Claim(IdentityModel.JwtClaimTypes.NickName, "root"));
                cliams.Add(new Claim("eMail", "10000@qq.com"));
            }


            return Task.CompletedTask;
        }
    }
}
